#!/usr/bin/env python3
"""
Execute Manim animation files.

This module provides functionality to execute Manim animation files with various
quality settings and preview options.

Usage:
    from execute_manim import execute_manim_file
    
    # Execute with default settings
    execute_manim_file("my_animation.py")
    
    # Execute with high quality and no preview
    execute_manim_file("my_animation.py", quality="h", preview=False)
"""

import os
import sys
import argparse
import subprocess
from pathlib import Path
from typing import Optional


# Quality settings mapping
QUALITY_SETTINGS = {
    "l": "low",
    "m": "medium", 
    "h": "high"
}


def validate_file_path(file_path: str) -> Optional[Path]:
    """
    Validate that the file path exists and is a Python file.
    
    Args:
        file_path: Path to the file to validate
        
    Returns:
        Path object if valid, None otherwise
    """
    path = Path(file_path)
    
    if not path.exists():
        print(f"Error: File {path} does not exist.")
        return None
    
    if not path.is_file():
        print(f"Error: {path} is not a file.")
        return None
    
    if path.suffix != '.py':
        print(f"Warning: {path} is not a Python file.")
    
    return path


def build_manim_command(file_path: Path, quality: str, preview: bool) -> str:
    """
    Build the manim command string.
    
    Args:
        file_path: Path to the Python file
        quality: Quality setting (l, m, h)
        preview: Whether to preview the animation
        
    Returns:
        The complete manim command string
    """
    preview_flag = "p" if preview else ""
    command = f"manim -{preview_flag}q{quality} {file_path}"
    return command


def execute_manim_file(file_path: str, quality: str = "l", preview: bool = True) -> int:
    """
    Execute a Manim animation file.
    
    Args:
        file_path: Path to the Python file containing Manim code
        quality: Quality of the animation (l=low, m=medium, h=high)
        preview: Whether to preview the animation after rendering
        
    Returns:
        The return code from the manim command (0 for success)
    """
    # Validate inputs
    if quality not in QUALITY_SETTINGS:
        print(f"Error: Invalid quality setting '{quality}'. Must be one of: {list(QUALITY_SETTINGS.keys())}")
        return 1
    
    validated_path = validate_file_path(file_path)
    if not validated_path:
        return 1
    
    # Build and execute command
    command = build_manim_command(validated_path, quality, preview)
    
    print(f"Executing: {command}")
    print(f"Quality: {QUALITY_SETTINGS[quality]}")
    print(f"Preview: {'enabled' if preview else 'disabled'}")
    
    try:
        result = subprocess.run(
            command, 
            shell=True, 
            check=True,
            capture_output=False,  # Allow output to be shown in real-time
            text=True
        )
        
        print(f"Animation rendered successfully!")
        return result.returncode
        
    except subprocess.CalledProcessError as e:
        print(f"Error executing manim: {e}")
        print(f"Command failed with return code: {e.returncode}")
        return e.returncode
    except FileNotFoundError:
        print("Error: 'manim' command not found. Please ensure Manim is installed and in your PATH.")
        return 1
    except Exception as e:
        print(f"Unexpected error during execution: {e}")
        return 1


def check_manim_installation() -> bool:
    """
    Check if Manim is properly installed.
    
    Returns:
        True if Manim is available, False otherwise
    """
    try:
        result = subprocess.run(
            ["manim", "--version"], 
            capture_output=True, 
            text=True, 
            check=True
        )
        print(f"Manim version: {result.stdout.strip()}")
        return True
    except (subprocess.CalledProcessError, FileNotFoundError):
        print("Warning: Manim not found or not working properly.")
        return False


def main():
    """Command-line interface for executing Manim files."""
    parser = argparse.ArgumentParser(
        description="Execute a Manim animation file",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  # Execute with default settings (low quality, with preview)
  python execute_manim.py my_animation.py
  
  # Execute with high quality
  python execute_manim.py my_animation.py -q h
  
  # Execute without preview
  python execute_manim.py my_animation.py -n
  
  # Execute with medium quality and no preview
  python execute_manim.py my_animation.py -q m -n
"""
    )
    
    parser.add_argument(
        "file", 
        type=str, 
        help="Path to the Python file containing Manim code"
    )
    parser.add_argument(
        "--quality", "-q", 
        type=str, 
        choices=["l", "m", "h"], 
        default="l", 
        help="Quality of the animation (l=low, m=medium, h=high)"
    )
    parser.add_argument(
        "--no-preview", "-n", 
        action="store_true", 
        help="Don't preview the animation after rendering"
    )
    parser.add_argument(
        "--check-install", "-c",
        action="store_true",
        help="Check if Manim is properly installed"
    )
    
    args = parser.parse_args()
    
    if args.check_install:
        if check_manim_installation():
            print("Manim is properly installed.")
            return 0
        else:
            print("Manim installation check failed.")
            return 1
    
    return execute_manim_file(args.file, args.quality, not args.no_preview)


if __name__ == "__main__":
    sys.exit(main())